package com.ease.common.reflect;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.Map;

public class TypeReflectSample<E> {

	private int primitiveType;
	private Map<E, ? extends Integer> parameterizedType;
	private E typeVariable;
	private E[] genericArrayType;

	public static void p(Object object) {
		System.out.println(object);
	}

	public static void p(Type type) {
		p("Class: " + type.getClass() + " Type: " + type);
	}

	public static void test() {
		Class<?> typeReflectionTest = TypeReflectSample.class;
		p(typeReflectionTest.getGenericSuperclass());
		try {

			p("PrimitiveType-->");
			Field primitiveTypeField = typeReflectionTest.getDeclaredField("primitiveType");
			Type primitiveType = primitiveTypeField.getGenericType();
			p(primitiveType);

			p("ParameterizedType-->");
			Field parameterizedTypeField = typeReflectionTest.getDeclaredField("parameterizedType");
			Type parameterizedType = parameterizedTypeField.getGenericType();
			p(parameterizedType);

			// get WildcardType
			p("actualType/WildcardType-->");
			ParameterizedType targetParameterizedType = (ParameterizedType) parameterizedType;
			Type[] actualTypes = targetParameterizedType.getActualTypeArguments();
			for (Type actualType : actualTypes) {

				p(actualType);

				if (actualType instanceof WildcardType) {
					WildcardType wildcardType = (WildcardType) actualType;
					for (Type upperBound : wildcardType.getUpperBounds()) {
						p(upperBound);
					}
					for (Type lowerBound : wildcardType.getLowerBounds()) {
						p(lowerBound);
					}
				}
			}

			p("TypeVariable-->");
			Field typeVariableField = typeReflectionTest.getDeclaredField("typeVariable");
			Type typeVariable = typeVariableField.getGenericType();
			p(typeVariable);

			p("GenericArrayType-->");
			Field genericArrayTypeField = typeReflectionTest.getDeclaredField("genericArrayType");
			Type genericArrayType = genericArrayTypeField.getGenericType();
			p(genericArrayType);

		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		TypeReflectSample.test();
	}
}
